package com.jh.netty.instruction;

import com.jh.netty.instruction.datapacket.CmdGetDotStatus;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;

import static com.jh.netty.instruction.DataPacketCMD.*;

/**
 * 数据包格式
 * 数据包中数据都是16进制，不包括前缀0x
 *
 * 通讯协议： 六.指令代码表
 *          三. 通讯过程（3、4）
 */
@Data
public class DataPacket {

    /**
     * 命令码 1byte，十六进制字符串
     * Ox81(接收正常),0x82(请求重发),0x83(无效命令码),0x84(无效数据)
     * @see DataPacketCMD
     */
    private String cmdCode;

    @Setter(AccessLevel.NONE)
    private DataPacketCMD cmd;

    /**
     * 数据码：数据内容
     *
     * @see CmdGetDotStatus
     * @see com.jh.netty.instruction.datapacket.ControllerHistoryResponseData
     * @see com.jh.netty.instruction.datapacket.DoorParam
     */
    private String dataCodeText;

    public void setCmdCode(String cmdCode) {
        this.cmdCode = cmdCode;
        this.cmd = DataPacketCMD.cmd(cmdCode);
    }

    /**
     * 命令码 数据码1 数据码2 数据码3 ...
     *
     * 组合命令和数据码
     */
    public String getDataPacket() {
        return cmdCode + dataCodeText;
    }

    public String getDataPacketLength() {
        String dp = cmdCode + dataCodeText;
        int len = dp.length() / 2;
        return String.format("%04x", len);
    }

    /**
     * 通过解析指令构造{@link DataPacket}
     *
     * @param instruction 指令
     * @return {@link DataPacket}
     */
    public static DataPacket parse(String instruction) {
        DataPacket dp = new DataPacket();
        dp.setCmdCode(instruction.substring(0, 2));
        dp.setDataCodeText(instruction.substring(2));
        return dp;
    }

    /**
     * 是否接收正常（）
     * 当通信包正确且主机对某台控制器下载数据时，控制器回应的通信包中，数据包只包含一个命
     * 令码字节，
     */
    public boolean isOk() {
        return CMD_OK.getCmd().equals(cmdCode);
    }

    /**
     * 是否是重发
     */
    public boolean isResend() {
        return CMD_Request_Resend.getCmd().equals(cmdCode);
    }

    /**
     * 是否是无效命令码
     */
    public boolean isValidCmdCode() {
        return CMD_INVALID_CMD_CODE.getCmd().equals(cmdCode);
    }

    /**
     * 当通信包正确且主机请求从某台控制器上载数据时，控制器回应的通信包中，数据包由命令码
     * 和若干数据组成
     * <p>
     * 数据是否已 "全部上载"
     */
    public boolean isDataUploaded() {
        return CMD_DATA_ALL_UPLOAD.getCmd().equals(cmdCode);
    }
}
